/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pe;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import pe.com.ColaUnidadesSinProcesar;
import pe.com.unidades.Telefono;
import pe.com.ColaProcesamiento;
import pe.com.procesos.ProcesadorArchivoFTP;
import pe.com.procesos.ProcesadorPlaca;
import pe.com.procesos.ProcesadorTelefono;
import pe.com.procesos.ProcesarAsterisk;
import pe.com.unidades.Archivo;
import pe.com.unidades.Chip;
import pe.com.unidades.Placa;
import pe.com.procesos.ProcesadorCorreo;
import pe.com.procesos.ProcesadorSunarp;
import pe.com.unidades.Vehiculo;

/**
 *
 * @author romulogalindo
 */
public class Jaguar {

    Connection con1;
    Statement st;
    String driver1 = "";
    String server1 = "";
    String port1 = "";
    String database1 = "";
    String user1 = "";
    String password1 = "";
    String proceso = "A";
    String tipo = "M";
    String limit = "1";
    //------FTP---------
    String ftpuser = "";
    String ftppassword = "";
    String ftpserver = "";
    String ftpport = "";
    String ftpfilename = "";
    String ftpfileformat = "";
    String store = "";
    //------CORREO------
    String correoDir;
    String correoAnhio;

    boolean procesoActivo = true;

    ProcesadorCorreo agajo;

    public Jaguar(String[] args) throws InterruptedException {
//    public Jaguar() throws InterruptedException {
        Long s1 = System.currentTimeMillis();
        con1 = DO(args);
//        con1 = DO();
        try {
            Statement st = con1.createStatement();
            ResultSet rpta;
            switch (proceso) {
                case "N":
                    rpta = st.executeQuery("select * from wftelefo.pbprocesar_telefono('" + tipo + "', " + limit + ");");
                    while (rpta.next()) {
                        ColaUnidadesSinProcesar.nuevaUnidad(new Telefono(1, rpta.getString("pbprocesar_telefono"), tipo));
                    }
                    break;
                case "P":
                    rpta = st.executeQuery("select pbpapele_pbimpveh_select from vehmay.pbpapele_pbimpveh_select();");
                    while (rpta.next()) {
                        ColaUnidadesSinProcesar.nuevaUnidad(new Placa(rpta.getString("pbpapele_pbimpveh_select")));
                    }
                    break;
                case "X":
                    rpta = st.executeQuery("select pbpapele_pbimpveh_select from vehmay.pbpapele_pbimpveh_select();");
                    while (rpta.next()) {
                        ColaUnidadesSinProcesar.nuevaUnidad(new Placa(rpta.getString("pbpapele_pbimpveh_select")));
                    }
                    break;
                case "F":
                    rpta = st.executeQuery("select * from " + store + "()");
                    Archivo archivo = new Archivo();
                    while (rpta.next()) {
                        archivo.addContenido(rpta.getString(1));
//                        ColaUnidadesSinProcesar.nuevaUnidad(new Archivo(rpta.getString(1)));
                    }
                    ColaUnidadesSinProcesar.nuevaUnidad(archivo);

                    break;
                case "A":
                    rpta = st.executeQuery("select pbtelefono_asterisk_select from arllamad.pbtelefono_asterisk_select();");
                    while (rpta.next()) {
                        ColaUnidadesSinProcesar.nuevaUnidad(new Chip(rpta.getString("pbtelefono_asterisk_select")));
                    }
                    break;
                case "C":
                    st.close();
                    agajo = new ProcesadorCorreo(correoDir, correoAnhio);
                    break;
                case "S":
                    System.out.println("Ejecutando:" + "select sunarp_pendientes from wfvehicu.sunarp_pendientes();");
                    rpta = st.executeQuery("select sunarp_pendientes from wfvehicu.sunarp_pendientes();");
//                    rpta = st.executeQuery("select sunarp_pendientes from wfvehicu.sunarp_pendientes() where sunarp_pendientes = 'F7N270';");
                    while (rpta.next()) {
                        ColaUnidadesSinProcesar.nuevaUnidad(new Vehiculo(rpta.getString("sunarp_pendientes")));
                    }
                    break;
            }
            ////Elementos de prueba
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("B6G685"));
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("C4W653"));
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("C3T454"));
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("B4Y652"));
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("D8B660"));
//                    ColaUnidadesSinProcesar.nuevaUnidad(new Placa("D8L696"));
            ////Fin
        } catch (SQLException ep) {
            System.out.println("Errorr:\n[Class] " + ep.getClass() + "\n" + ep.getMessage());
            ep.printStackTrace();
            return;
        } finally {
            try {
                con1.close();
            } catch (SQLException ep) {
            }
        }
        System.out.println("[Jaguar] Cantidad de datos a procesar: " + ColaUnidadesSinProcesar.taskssize());

        ColaProcesamiento colaProcesamiento = new ColaProcesamiento(args);
//        ColaProcesamiento colaProcesamiento = new ColaProcesamiento();
        colaProcesamiento.start();

        ExecutorService executor = null;
        switch (proceso) {
            case "N":
                executor = Executors.newFixedThreadPool(5);
                while (!ColaUnidadesSinProcesar.isEmpty()) {
                    ProcesadorTelefono procesadorTelefono = new ProcesadorTelefono((Telefono) ColaUnidadesSinProcesar.consumirUnidad());
                    executor.execute(procesadorTelefono);
                }
                executor.shutdown();
                break;
            case "P":
                int cant_thread = ColaUnidadesSinProcesar.taskssize();
                if (cant_thread > 0 & cant_thread < 100) {
                    if (cant_thread > 5) {
                        cant_thread = 3;
                    }
                } else if (cant_thread > 100 & cant_thread < 2000) {
                    cant_thread = 5;
                } else if (cant_thread >= 2000 & cant_thread < 5000) {
                    cant_thread = 10;
                } else if (cant_thread >= 5000) {
                    cant_thread = 20;
                }
                int pedidos = ColaUnidadesSinProcesar.taskssize() / cant_thread;
                int pedidos_extra = ColaUnidadesSinProcesar.taskssize() % cant_thread;
                if (pedidos_extra > 0) {
                    cant_thread = cant_thread + 1;
                }
                System.out.println("pedidos:" + pedidos + "::pedidos_extra:" + pedidos_extra + ", cant hilos:" + cant_thread);
                if (pedidos_extra > 0) {
                    executor = Executors.newFixedThreadPool(cant_thread);
                    for (int i = 0; i < (cant_thread); i++) {
                        List<Placa> placas = new ArrayList<>();
                        if (i == cant_thread - 1) {
                            for (int x = 0; x < pedidos_extra; x++) {
                                try {
                                    placas.add((Placa) ColaUnidadesSinProcesar.consumirUnidad());
                                } catch (InterruptedException ep) {
                                    System.out.println(">" + ep.getMessage());
                                }
                            }
                        } else {
                            for (int x = 0; x < pedidos; x++) {
                                try {
                                    placas.add((Placa) ColaUnidadesSinProcesar.consumirUnidad());
                                } catch (InterruptedException ep) {
                                    System.out.println(">" + ep.getMessage());
                                }
                            }

                        }
                        System.out.println("Generando hilo[" + i + "] de " + placas.size() + " placas");
                        ProcesadorPlaca procesadorPlaca = new ProcesadorPlaca(placas, i);
                        executor.execute(procesadorPlaca);
                    }
                } else {
                    executor = Executors.newFixedThreadPool(cant_thread);
                    for (int i = 0; i < cant_thread; i++) {
                        List<Placa> placas = new ArrayList<>();
                        for (int x = 0; x < pedidos; x++) {
                            try {
                                placas.add((Placa) ColaUnidadesSinProcesar.consumirUnidad());
                            } catch (InterruptedException ep) {
                                System.out.println(">" + ep.getMessage());
                            }
                        }
                        ProcesadorPlaca procesadorPlaca = new ProcesadorPlaca(placas, i);
                        executor.execute(procesadorPlaca);
                    }
                }
                System.out.println(">> antes del extra" + ColaUnidadesSinProcesar.taskssize());
                executor.shutdown();
                break;
            case "X":
                break;
            case "F":
                ProcesadorArchivoFTP ftp = new ProcesadorArchivoFTP(ftpserver, Integer.parseInt(ftpport), ftpuser, ftppassword, ftpfilename, ftpfileformat);
                boolean p = ftp.procesar((Archivo) ColaUnidadesSinProcesar.consumirUnidad());
                procesoActivo = p == true ? false : true;
                break;
            case "A":
                ProcesarAsterisk pa = new ProcesarAsterisk();
                pa.procesar();
                procesoActivo = false;
                break;
            case "C":
                agajo.procesar(DO(args));
                break;
            case "S":
                executor = Executors.newFixedThreadPool(5);
                while (!ColaUnidadesSinProcesar.isEmpty()) {
                    ProcesadorSunarp procesadorVehiculoSunarp = new ProcesadorSunarp((Vehiculo) ColaUnidadesSinProcesar.consumirUnidad());
                    executor.execute(procesadorVehiculoSunarp);
                }
                executor.shutdown();
                break;
        }
        if (!procesoActivo) {
            s1 = System.currentTimeMillis() - s1;
            int milseconds = (int) (s1 % 1000);
            int seconds = (int) (s1 / 1000) % 60;
            int minutes = (int) ((s1 / (1000 * 60)) % 60);
            int hours = (int) ((s1 / (1000 * 60 * 60)) % 24);

            System.out.println("Tiempo : " + hours + "hrs " + minutes + "min  " + seconds + "seg y " + milseconds + "ms");
            try {
                ColaUnidadesSinProcesar.nuevaUnidad("END");
                colaProcesamiento.stopme();
                colaProcesamiento = null;
                procesoActivo = false;
                if (executor != null) {
                    executor.shutdown();
                    executor.awaitTermination(0, TimeUnit.NANOSECONDS);
                }
            } catch (Exception ep) {
//                System.out.println("Error al cerrarla cola: " + ep.getMessage());
                ep.printStackTrace();
            }
        }
        while (procesoActivo) {
            try {
                if (executor.isTerminated() & ColaProcesamiento.taskssize() == 0 & colaProcesamiento.proceso()) {
                    s1 = System.currentTimeMillis() - s1;
                    int milseconds = (int) (s1 % 1000);
                    int seconds = (int) (s1 / 1000) % 60;
                    int minutes = (int) ((s1 / (1000 * 60)) % 60);
                    int hours = (int) ((s1 / (1000 * 60 * 60)) % 24);

                    System.out.println("Tiempo : " + hours + "hrs " + minutes + "min  " + seconds + "seg y " + milseconds + "ms");
                    colaProcesamiento.stopme();
                    colaProcesamiento = null;
                    procesoActivo = false;
                    executor.shutdown();
                    executor.awaitTermination(0, TimeUnit.NANOSECONDS);
                }
            } catch (Exception ep2) {
                procesoActivo = false;
            }
        }
    }

    public Connection DO() {
        try {
            Class.forName("org.postgresql.Driver");
            System.out.println("Cargando driver\t[OK]");
            con1 = DriverManager.getConnection("jdbc:postgresql://wf1.accesocrediticio.com:5432/WFACR", "rgalindo", "W41t3Kn1g4t");
//            con1 = DriverManager.getConnection("jdbc:postgresql://wf1.accesocrediticio.com:5432/WFACR", "mdiaz", "acceso123456");
//            st = con1.createStatement();
            return con1;
        } catch (ClassNotFoundException | SQLException ep) {
            System.out.println("Errorr:\n[Class] " + ep.getClass() + "\n" + ep.getMessage());
            return null;
        }
    }

    public Connection DO(String[] args) {
        for (String arg : args) {
            String keyName = arg.split("=")[0];
            switch (keyName) {
                case "-driver1": {
                    driver1 = arg.split("=")[1];
                    break;
                }
                case "-server1": {
                    server1 = arg.split("=")[1];
                    break;
                }
                case "-port1": {
                    port1 = arg.split("=")[1];
                    break;
                }
                case "-database1": {
                    database1 = arg.split("=")[1];
                    break;
                }
                case "-user1": {
                    user1 = arg.split("=")[1];
                    break;
                }
                case "-password1": {
                    password1 = arg.split("=")[1];
                    break;
                }
                case "-proceso": {
                    proceso = arg.split("=")[1];
                    break;
                }
                case "-tipo": {
                    tipo = arg.split("=")[1];
                    break;
                }
                case "-limit": {
                    limit = arg.split("=")[1];
                    break;
                }
                case "-ftpuser": {
                    ftpuser = arg.split("=")[1];
                    break;
                }
                case "-ftppass": {
                    ftppassword = arg.split("=")[1];
                    break;
                }
                case "-ftpserver": {
                    ftpserver = arg.split("=")[1];
                    break;
                }
                case "-ftpport": {
                    ftpport = arg.split("=")[1];
                    break;
                }
                case "-ftpfilename": {
                    ftpfilename = arg.split("=")[1];
                    break;
                }
                case "-ftpfileformat": {
                    ftpfileformat = arg.split("=")[1];
                    break;
                }
                case "-store": {
                    store = arg.split("=")[1];
                    break;
                }
                case "-dir": {
                    correoDir = arg.split("=")[1];
                    break;
                }
                case "-anhio": {
                    correoAnhio = arg.split("=")[1];
                    break;
                }
            }
            /*
             String ftpUser = "";
             String ftppassword = "";
             String ftpserver = "";
             String ftpport = "";
             String ftpfilename = "";
             String ftpfileformat = "";
             String store = "";
             */
        }
        System.out.println("[Jaguar] Iniciando");
        try {
            if (driver1.contentEquals("")) {
                driver1 = "org.postgresql.Driver";
                System.out.println("Cargando driver por default....:" + driver1);
            }
            Class.forName(driver1);
            System.out.println("[Jaguar] Cargando driver Postgresql [OK]");
        } catch (ClassNotFoundException ep) {
            System.out.println("Error-cargando driver:\n[Class] " + ep.getClass() + "\n" + ep.getMessage());
            return null;
        }
        try {
//            System.out.println("jdbc:postgresql://" + server1 + ":" + port1 + "/" + database1 + "," + user1 + "" + "," + password1 + "");
            con1 = DriverManager.getConnection("jdbc:postgresql://" + server1 + ":" + port1 + "/" + database1, "" + user1 + "", "" + password1 + "");
            return con1;
        } catch (SQLException ep) {
            System.out.println("Error:\n[Class] " + ep.getClass() + "->\n" + ep.getMessage());
            return null;
        }

    }

    public static void main(String[] args) {
        try {
            new Jaguar(args);
//            new Jaguar();
        } catch (InterruptedException ep) {
            System.out.println(">" + ep.getMessage());
        }
    }

}
